
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>SpringBoot学习指南 - 学习卡片</title>
      <style>
        body { font-family: sans-serif; background-color: #f0f8ff; color: #333; display: flex; flex-direction: column; align-items: center; padding: 50px 20px; }
        .header h1 { font-size: 32px; }
        .grid-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; width: 100%; max-width: 1200px; }
        .card-container { perspective: 1200px; cursor: pointer; height: 250px; }
        .card { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: transform 0.7s; border-radius: 16px; box-shadow: 0 4px 16px rgba(0,0,0,0.08); }
        .card-container.flipped .card { transform: rotateY(180deg); }
        .card-face { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; display: flex; flex-direction: column; box-sizing: border-box; border-radius: 16px; background-color: #fff; padding: 24px; }
        .card-back { background-color: #f0fff4; transform: rotateY(180deg); justify-content: space-between; }
        .card-category { font-size: 14px; color: #0052d9; margin-bottom: 8px; font-weight: 500; }
        .card-question { font-size: 20px; font-weight: 500; flex-grow: 1; display: flex; align-items: center; justify-content: center; text-align: center; }
        .card-answer-wrapper { flex-grow: 1; overflow-y: auto; }
        .card-answer { font-size: 15px; line-height: 1.7; }
        .card-footer { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 16px; margin-top: 16px; }
        .card-source { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 12px; margin-top: 12px; }
      </style>
    </head>
    <body>
      <div class="header">
        <h1>SpringBoot学习指南 - 学习卡片</h1>
      </div>
      <div class="grid-container">
        
    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">SpringBoot的核心设计思想是什么？它如何提升开发效率？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">SpringBoot的核心设计思想是“约定优于配置”。这意味着框架提供了大量默认配置，开发者无需进行繁琐的样板化配置即可快速搭建和开发应用。当默认值不满足需求时，可以通过配置文件（如Properties或YAML）进行覆盖。这种方式通过约定减少了配置工作，从而显著提升了开发效率。</div>
          </div>
          <div class="card-source">来源: 二、SpringBoot介绍 -> 2.1 约定优于配置</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">当在SpringBoot项目中引入 `spring-boot-starter-web` 依赖后，框架会做出哪些约定或自动配置？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">引入 `spring-boot-starter-web` 后，SpringBoot会约定这是一个Web开发环境，并自动配置以下内容：1. 默认使用Spring MVC框架。2. 自动导入Spring MVC的相关依赖。3. 内置一个Tomcat容器，使得项目可以通过main方法或JAR包独立运行。4. 自动导入日志相关依赖 `spring-boot-starter-logging`。</div>
          </div>
          <div class="card-source">来源: 2.2 SpringBoot中的约定</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">在SpringBoot中如何实现多环境配置，并在部署时激活指定的环境？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">首先，在 `application.yml` 文件中通过 `spring.profiles.active: 环境名` 来指定默认激活的环境。然后，为每个环境创建对应的配置文件，命名为 `application-环境名.yml`。在部署时，可以通过命令行参数激活特定环境，例如：`java -jar jar文件 --spring.profiles.active=环境名`。</div>
          </div>
          <div class="card-source">来源: 5.2 多环境配置</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">特性</div>
          <div class="card-question">在SpringBoot中，`@Configuration` 和 `@Bean` 注解的作用分别是什么？它们如何替代传统的XML配置？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">特性</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">`@Configuration` 注解用于标记一个类为配置类，其作用相当于XML配置文件中的 `<beans>` 标签。`@Bean` 注解用于方法上，声明创建一个Bean并将其放入Spring容器中，其作用相当于XML中的 `<bean>` 标签。默认情况下，方法名即为Bean的ID。</div>
          </div>
          <div class="card-source">来源: 4.1 @Configuration和@Bean</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">SpringBoot默认会从哪些路径加载静态资源？这些路径的优先级顺序是怎样的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">SpringBoot默认从以下四个classpath路径加载静态资源：`/META-INF/resources`, `/resources`, `/static`, `/public`。它们的优先级顺序为：`META-INF/resources` > `resources` > `static` > `public`。</div>
          </div>
          <div class="card-source">来源: 八、SpringBoot静态资源处理</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">模式</div>
          <div class="card-question">在既想保留SpringBoot自动配置的便利性，又需要添加自定义MVC配置（如拦截器）时，推荐的做法是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">模式</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">推荐的做法是定义一个配置类并实现 `WebMvcConfigurer` 接口，然后重写相应的方法（如 `addInterceptors` 添加拦截器或 `addResourceHandlers` 添加静态资源处理器）。这样做可以在不使用 `@EnableWebMvc` 注解（该注解会完全覆盖SpringBoot的自动配置）的情况下，保留默认配置并增加额外的自定义功能。</div>
          </div>
          <div class="card-source">来源: 九、SpringBoot自定义静态资源处理</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">为什么SpringBoot官方不推荐使用JSP作为视图技术？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">官方不推荐使用JSP主要有两个原因：1. 内嵌的Tomcat容器在使用JSP时只支持war包的打包方式，不支持可执行的jar包。2. 像Jetty这样的其他内嵌容器不支持JSP。</div>
          </div>
          <div class="card-source">来源: 七、SpringBoot提供视图支持</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">为什么SpringBoot中的404（页面未找到）错误通常不会被全局异常处理器（@RestControllerAdvice）捕获？应如何优雅地处理404异常？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">因为SpringBoot对于404问题不会抛出异常，而是将其转发到默认的 `/error` 请求路径进行处理，所以全局异常处理器无法捕获它。要优雅地处理404，可以自定义一个继承自 `BasicErrorController` 的Controller，并覆盖其 `error` (处理JSON响应) 和 `errorHtml` (处理HTML响应) 方法，从而实现自定义的404错误返回格式。</div>
          </div>
          <div class="card-source">来源: Spring Boot优雅地处理404异常</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">模式</div>
          <div class="card-question">如何使用 `ResponseBodyAdvice` 接口来统一包装Controller的返回数据格式，以避免在每个接口中重复编写封装逻辑？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">模式</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">通过实现 `ResponseBodyAdvice` 接口并使用 `@ControllerAdvice` 注解，可以拦截Controller方法的返回值。在其 `beforeBodyWrite` 方法中，判断返回值是否已经被包装过，如果没有，则将其统一封装到一个标准的结果类（如包含code, message, data字段的Result对象）中再返回给客户端。这实现了对返回结果的统一、非侵入式处理。</div>
          </div>
          <div class="card-source">来源: 十六 、控制层统一返回格式 -> 统一包装</div>
        </div>
      </div>
    </div>

      </div>
    </body>
    </html>
